<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title>Template • TodoMVC</title>
		<link rel="stylesheet" href="node_modules/todomvc-common/base.css">
		<link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
		<link rel="stylesheet" href="css/app.css">
		<!-- {/* 引入react依赖库 */} -->
		<script src="lib/react/react.development.js"></script>
		<script src="lib/react/react-dom.development.js"></script>
		<script src="lib/babel.min.js"></script>
	</head>
	<body>
		<section class="todoapp" id="root">
			
		</section>
		<footer class="info">
			<p>Double-click to edit a todo</p>
			<!-- {/* Remove the below line ↓ */} -->
			<p>Template by <a href="http://sindresorhus.com">Sindre Sorhus</a></p>
			<!-- {/* Change this out with your name and url ↓ */} -->
			<p>Created by <a href="http://todomvc.com">you</a></p>
			<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
		</footer>
		<!-- {/* Scripts here. Don't remove ↓ */} -->
		<script src="node_modules/todomvc-common/base.js"></script>
		<script type="text/babel">
				// 声明react组件
				class TodoMVC extends React.Component {
					constructor(props){
						super(props);
						// 声明state
						this.state = {
							newTodoText: '', // 新增的todo文本
							editId: '',  // 用于标识被编辑的元素id
							preEditValue: '', // 用于备份需要编辑的输入框原来的值
							filterState: 'All', // 过滤条件 All   Active  Completed
							todoList: [ 
								{
									id: '1',
									text: '吃饭',
									isCompleted: true
								},
								{
									id: '2',
									text: '上班',
									isCompleted: false
								}
							]
						}
					}
					// 声明input输入框的变化通用方法
					// 箭头函数可以避免在构造函数中重新bind(this)
					handleInputChange = (key,e)=>{
						var value = e.target.value;
						this.setState({
							[key]:value
						})
					}
					// 用于处理新增的输入事件
					handleNewTodoAdd = (e)=>{
						// 判断 是回撤才新增
						var keyCode = e.keyCode;
						if(keyCode == 13){
							// 一再强调了 state中的对象 需要克隆出来
							var todoList = [...this.state.todoList];
							var inputValue = e.target.value;
							// 做空判断
							if(inputValue == '') return;
							// 构建
							var todo = {
								id: new Date().getTime().toString(), // 用时间戳做id
								text: inputValue,
								isCompleted: false, // 默认非完成状态
							}
							// 添加到列表
							todoList.push(todo);
							// 更新到state
							this.setState({
								todoList
							})
							// 清空输入框
							this.setState({
								newTodoText: ''
							})
						}
					}
					handleItemCheckedChange = (id,e)=>{
						// 克隆todoList
						var todoList = [...this.state.todoList];
						// 根据id找到需要变化的todo
						// var todoItem = [...this.state.todoList.find(item=>item.id == id)];
						var newTodoList = todoList.map(item=>{
							if(item.id == id){
								item.isCompleted = !item.isCompleted;
							}
							return item;
						})
						// // 修改todoItem  toggle状态
						// todoItem.isCompleted = !todoItem.isCompleted;
						// 更新state 单独修改某一个没法写了...  
						// 所以要更新 必须把整个 state.todoList 替换成最新的
						this.setState({
							todoList: newTodoList
						})
					}
					// 当全选反选按钮被点击的时候触发
					handleAllCheckedChange = ()=>{
						// 1. 获取之前的状态
						var preIsAllCompleted = !this.state.todoList.some(item=>!item.isCompleted);
						// 2. 修改所有的列表使其和 preIsAllCompleted 相反
						var todoList = [...this.state.todoList];
						var newTodoList = todoList.map(item=>{
							item.isCompleted = !preIsAllCompleted;
							return item;
						})
						// 3. 修改state
						this.setState({
							todoList: newTodoList
						})
					}
					// 双击编辑事件
					handleEdit = (e,id)=>{
						// 找到当前元素
						var todoItem = this.state.todoList.find(item=>item.id == id);
						// 如果当前元素已完成,不允许被修改!
						if(todoItem.isCompleted){
							alert('当前元素已完成,不允许被编辑!');
							// 取消之前的编辑元素
							this.setState({
								editId: ''
							})
							return;
						}
						// 使当前行处于编辑状态
						this.setState((state,props)=>({
							editId: id
						}),()=>{
							// 希望编辑输入框显示之后 获取焦点
							var inputDom = e.target.parentNode.nextElementSibling;
							inputDom.focus();
						})
						// 备份当前行的text
						this.setState({
							preEditValue: todoItem.text
						})
						
					}
					// 处理编辑框的变化 
					handleEditChange = (e)=>{
						// 直接修改todoList?  能吗?
						 // 应该修改的是备份元素  直到 用户点击enter确定才存入todoList ; 如果用户点击esc,则还原
						this.setState({
							preEditValue: e.target.value
						})
					}
					// 编辑输入框  可能是enter 也可能是esc
					handleEditEnterOrEsc = (e,id)=>{
						var keyCode = e.keyCode;
						//如果是enter ,则应该更新到todoList
						if(keyCode == 13){
							var todoList = [...this.state.todoList];
							var todoItem = todoList.find(item=>item.id == id);
							todoItem.text = e.target.value;
							//修改todoList
							this.setState((state,props)=>({
								todoList
							}),()=>{
								// 还原编辑状态
								this.setState({
									editId: '',
									preEditValue: ''
								})
							})
						}
						// esc 取消 还原
						if(keyCode == 27){
							this.setState({
								editId: '',
								preEditValue: ''
							})
						}
					}
					// 删除某一个数据
					handleRemoveItem = (id)=>{
						// 可以通过找到下标删除 但是数据量小可以通过filter
						var todoList = [...this.state.todoList];
						var newTodoList = todoList.filter(item=> item.id != id);
						// 修改
						this.setState({
							todoList: newTodoList
						})
					}
					// 删除所有完成数据
					doClearCompleted = ()=>{
						var todoList = [...this.state.todoList];
						var newTodoList = todoList.filter(item => !item.isCompleted);
						this.setState({
							todoList: newTodoList
						})
					}
					// 改变过滤条件
					handleFilterChange = (filterState)=>{
						this.setState({
							filterState
						})
					}
					render(){
						// 渲染的数据列表
						var liList = this.state.todoList.map(item=>{
							// 判断是否处于完成状态
							var className = item.isCompleted?"completed":"";
							// 判断是否处于编辑状态  "completed editing"  
							// 完成状态和编辑状态是否应该共存 这个看个人的逻辑立即
							className += item.id == this.state.editId?" editing":"";
							var filterState = this.state.filterState; 
							// 如果是 Active  应该返回 没有完成的
							if(filterState == 'Active'){
								// 要不返回?
								if(item.isCompleted) return null;
							}else 
							// 如果是 completed  返回  所有完成的
							if(filterState == 'Completed'){
								if(!item.isCompleted) return null;
							}
							// 如果是All  应该无条件返回
							return (
								<li key={item.id} className={className}>
									<div className="view">
										<input className="toggle" type="checkbox" checked={item.isCompleted} onChange={e=>this.handleItemCheckedChange(item.id,e)}/>
										<label onDoubleClick={e=>this.handleEdit(e,item.id)}>{item.text}</label>
										<button className="destroy" onClick={()=>this.handleRemoveItem(item.id)}></button>
									</div>
										{/* 这里为了实现 esc 取消还原,所以value应该给备份数据进行绑定 */}
									<input className="edit" value={this.state.preEditValue} onChange={e=>this.handleEditChange(e)} onKeyUp={e=>this.handleEditEnterOrEsc(e,item.id)}/>
								</li>
								)
						})
						// 判断是否全选中  some()可以判断列表是否存在没有完成的项目
						var isAllCompleted = !this.state.todoList.some(item=>!item.isCompleted);
						// 剩余未完成数量
						var lastCount = this.state.todoList.filter(item=>!item.isCompleted).length;
						return (
							<div>
								<header className="header">
									<h1>todos</h1>
									<input className="new-todo" value={this.state.newTodoText} onChange={e=>this.handleInputChange('newTodoText',e)} onKeyUp={this.handleNewTodoAdd} placeholder="What needs to be done?" autoFocus />
								</header>
								{/* This section should be hidden by default and shown when there are todos */}
								<section className="main">
									<input id="toggle-all" className="toggle-all" checked={isAllCompleted} onChange={this.handleAllCheckedChange} type="checkbox" />
									<label htmlFor="toggle-all">Mark all as complete</label>
									<ul className="todo-list">
										{/* These are here just to show the structure of the list items */}
										{/* List items should get the class `editing` when editing and `completed` when marked as completed */}
										{liList}
									</ul>
								</section>
								{/* This footer should be hidden by default and shown when there are todos */}
								<footer className="footer">
									{/* This should be `0 items left` by default */}
									<span className="todo-count"><strong>{lastCount}</strong> item left</span>
									{/* Remove this if you don't implement routing */}
									<ul className="filters">
										<li>
											<a className={this.state.filterState=='All'?"selected":""} href="#/" onClick={()=>this.handleFilterChange('All')}>All</a>
										</li>
										<li>
											<a className={this.state.filterState=='Active'?"selected":""} href="#/active" onClick={()=>this.handleFilterChange('Active')}>Active</a>
										</li>
										<li>
											<a className={this.state.filterState=='Completed'?"selected":""} href="#/completed" onClick={()=>this.handleFilterChange('Completed')}>Completed</a>
										</li>
									</ul>
									{/* Hidden if no completed items are left ↓ */}
									<button className="clear-completed" onClick={this.doClearCompleted}>Clear completed</button>
								</footer>	
							</div>
						)
					}
				}
				ReactDOM.render(<TodoMVC/>,document.getElementById('root'));

		</script>
	</body>
</html>
